package cc.messcat.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Deque;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;

public class Collections {

	/**
	 * 用指定的比较器选出包含指定对象的元素，返回结果集
	 * 
	 * @param list
	 * @param object
	 * @param comparator
	 * @return
	 */
	public static <G> ArrayList<G> select(List<G> list, Object object, Comparator<Object> comparator) {
		ArrayList<G> result = new ArrayList<>();
		for (G e : list) {
			if (comparator.compare(e, object) == 0)
				result.add(e);
		}
		return result;
	}

	/**
	 * 用指定的比较器判断是否包含指定对象
	 * 
	 * @param list
	 * @param object
	 * @param comparator
	 * @return
	 */
	public static <G> boolean contains(List<G> list, Object object, Comparator<Object> comparator) {
		for (G e : list) {
			if (comparator.compare(e, object) == 0)
				return true;
		}
		return false;
	}

	/**
	 * 如果为null或者没有元素则返回 true
	 * 
	 * @param c
	 * @return
	 */
	public static boolean isEmpty(Collection<?> c) {
		return c == null || c.isEmpty();
	}

	/**
	 * 如果为null或者没有元素则返回 true
	 * 
	 * @param map
	 * @return
	 */
	public static boolean isEmpty(Map<?, ?> map) {
		return map == null || map.isEmpty();
	}

	/**
	 * 生成可变参数初始化的ArrayList
	 * 
	 * @param o
	 * @return
	 */
	@SafeVarargs
	public static <G> ArrayList<G> generateArrayList(G... o) {
		return new ArrayList<G>(Arrays.asList(o));
	}

	/**
	 * 生成可变参数初始化的LinkedList
	 * 
	 * @param o
	 * @return
	 */
	@SafeVarargs
	public static <G> LinkedList<G> generateLinkedList(G... o) {
		return new LinkedList<G>(Arrays.asList(o));
	}

	/**
	 * 生成以指定的键值对填充的新的HashMap
	 * 
	 * @param keys
	 * @param values
	 * @return
	 */
	public static <K, V> HashMap<K, V> generateHashMap(K[] keys, V[] values) {
		return (HashMap<K, V>) fill(new HashMap<K, V>(), keys, values);
	}

	/**
	 * 生成以固定值填充所有键的新的HashMap
	 * 
	 * @param keys
	 * @param value
	 * @return
	 */
	public static <K, V> HashMap<K, V> generateHashMap(K[] keys, V value) {
		return (HashMap<K, V>) fill(new HashMap<K, V>(), keys, value);
	}

	/**
	 * 生成以可变参数填充的新的HashMap，偶数索引为键
	 * 
	 * @param entrys
	 * @return
	 * @throws Exception
	 */
	public static <K, V> Map<K, V> generateHashMap(Object... entrys) {
		return fill(new HashMap<K, V>(), entrys);
	}

	/**
	 * 以指定的参数填充list
	 * @param list
	 * @param o
	 * @return
	 */
	@SafeVarargs
	public static <G> List<? super G> fill(List<? super G> list, G ... o) {
		if(o == null || o.length == 0) { return list;}
		
		for(G e : o) {
			list.add(e);
		}
		return list;
	}
	
	/**
	 * 可变参数填充，偶数索引为键
	 * 
	 * @param map
	 * @param entrys
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <K, V> Map<K, V> fill(Map<K, V> map, Object... entrys) {
		if (entrys == null || entrys.length == 0 || (entrys.length & 1) == 1) {
			throw new RuntimeException("map参数错误");
		}

		for (int i = 0; i < entrys.length; i++) {
			if ((i & 1) == 1) {
				map.put((K) entrys[i - 1], (V) entrys[i]);
			}
		}

		return map;
	}

	/**
	 * 以固定值填充所有键
	 * 
	 * @param map
	 * @param keys
	 * @param value
	 */
	public static <K, V> Map<K, V> fill(Map<K, V> map, K[] keys, V value) {
		if (keys == null) {
			throw new NullPointerException("键不能为空");
		}

		for (K e : keys) {
			map.put(e, value);
		}

		return map;
	}

	/**
	 * 以指定的键值对填充
	 * 
	 * @param map
	 * @param keys
	 * @param values
	 */
	@SuppressWarnings("unchecked")
	public static <K, V> Map<K, V> fill(Map<K, V> map, K[] keys, V[] values) {
		if (keys == null) {
			throw new NullPointerException("键不能为空");
		}

		if (values == null) {
			for (K e : keys) {
				map.put(e, null);
			}
		} else {
			Class<?> cla = values.getClass().getComponentType();
			Object placeHolder = cla.isInstance("") ? "" : cla.isInstance(0) ? 0 : null;
			for (int i = 0; i < keys.length; i++) {
				if (i < values.length) {
					map.put(keys[i], values[i]);
				} else {
					map.put(keys[i], (V) placeHolder);
				}
			}
		}

		return map;
	}

	public static <G extends Comparable<? super G>> void sort(List<G> list) {
		java.util.Collections.sort(list);
	}

	public static <G> void sort(List<G> list, Comparator<? super G> c) {
		java.util.Collections.sort(list, c);
	}

	public static <G> int binarySearch(List<? extends Comparable<? super G>> list, G key) {
		return java.util.Collections.binarySearch(list, key);
	}

	public static <G> int binarySearch(List<? extends G> list, G key, Comparator<? super G> c) {
		return java.util.Collections.binarySearch(list, key, c);
	}

	public static void reverse(List<?> list) {
		java.util.Collections.reverse(list);
	}

	public static void shuffle(List<?> list) {
		java.util.Collections.shuffle(list);
	}

	public static void shuffle(List<?> list, Random rnd) {
		java.util.Collections.shuffle(list, rnd);
	}

	public static void swap(List<?> list, int i, int j) {
		java.util.Collections.swap(list, i, j);

	}

	/**
	 * 使用指定元素替换指定列表中的所有元素
	 * 
	 * @param list
	 * @param obj
	 */
	public static <G> void replace(List<? super G> list, G obj) {
		java.util.Collections.fill(list, obj);
	}

	public static <G> void copy(List<? super G> dest, List<? extends G> src) {

		java.util.Collections.copy(dest, src);
	}

	public static <G extends Object & Comparable<? super G>> G min(Collection<? extends G> coll) {
		return java.util.Collections.min(coll);

	}

	public static <G> G min(Collection<? extends G> coll, Comparator<? super G> comp) {
		return java.util.Collections.min(coll, comp);

	}

	public static <G extends Object & Comparable<? super G>> G max(Collection<? extends G> coll) {
		return java.util.Collections.max(coll);

	}

	public static <G> G max(Collection<? extends G> coll, Comparator<? super G> comp) {

		return java.util.Collections.max(coll, comp);
	}

	public static void rotate(List<?> list, int distance) {

		java.util.Collections.rotate(list, distance);
	}

	public static <G> boolean replaceAll(List<G> list, G oldVal, G newVal) {
		return java.util.Collections.replaceAll(list, oldVal, newVal);

	}

	public static int indexOfSubList(List<?> source, List<?> target) {
		return java.util.Collections.indexOfSubList(source, target);

	}

	public static int lastIndexOfSubList(List<?> source, List<?> target) {
		return java.util.Collections.lastIndexOfSubList(source, target);

	}

	public static <G> Collection<G> unmodifiableCollection(Collection<? extends G> c) {
		return java.util.Collections.unmodifiableCollection(c);

	}

	public static <G> Set<G> unmodifiableSet(Set<? extends G> s) {

		return java.util.Collections.unmodifiableSet(s);
	}

	public static <G> SortedSet<G> unmodifiableSortedSet(SortedSet<G> s) {
		return java.util.Collections.unmodifiableSortedSet(s);

	}

	public static <G> List<G> unmodifiableList(List<? extends G> list) {
		return java.util.Collections.unmodifiableList(list);

	}

	public static <K, V> Map<K, V> unmodifiableMap(Map<? extends K, ? extends V> m) {
		return java.util.Collections.unmodifiableMap(m);

	}

	public static <K, V> SortedMap<K, V> unmodifiableSortedMap(SortedMap<K, ? extends V> m) {
		return java.util.Collections.unmodifiableSortedMap(m);

	}

	public static <G> Collection<G> synchronizedCollection(Collection<G> c) {
		return java.util.Collections.synchronizedCollection(c);
	}

	public static <G> Set<G> synchronizedSet(Set<G> s) {
		return java.util.Collections.synchronizedSet(s);

	}

	public static <G> SortedSet<G> synchronizedSortedSet(SortedSet<G> s) {
		return java.util.Collections.synchronizedSortedSet(s);

	}

	public static <G> List<G> synchronizedList(List<G> list) {
		return java.util.Collections.synchronizedList(list);

	}

	public static <K, V> Map<K, V> synchronizedMap(Map<K, V> m) {
		return java.util.Collections.synchronizedMap(m);

	}

	public static <K, V> SortedMap<K, V> synchronizedSortedMap(SortedMap<K, V> m) {

		return java.util.Collections.synchronizedSortedMap(m);
	}

	public static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> type) {
		return java.util.Collections.checkedCollection(c, type);

	}

	public static <E> Set<E> checkedSet(Set<E> s, Class<E> type) {

		return java.util.Collections.checkedSet(s, type);
	}

	public static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s, Class<E> type) {
		return java.util.Collections.checkedSortedSet(s, type);

	}

	public static <E> List<E> checkedList(List<E> list, Class<E> type) {
		return java.util.Collections.checkedList(list, type);

	}

	public static <K, V> Map<K, V> checkedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) {
		return java.util.Collections.checkedMap(m, keyType, valueType);

	}

	public static <K, V> SortedMap<K, V> checkedSortedMap(SortedMap<K, V> m, Class<K> keyType, Class<V> valueType) {
		return java.util.Collections.checkedSortedMap(m, keyType, valueType);

	}

	public static <G> Iterator<G> emptyIterator() {
		return java.util.Collections.emptyIterator();

	}

	public static <G> ListIterator<G> emptyListIterator() {
		return java.util.Collections.emptyListIterator();

	}

	public static <G> Enumeration<G> emptyEnumeration() {
		return java.util.Collections.emptyEnumeration();

	}

	public static final <G> Set<G> emptySet() {
		return java.util.Collections.emptySet();

	}

	public static final <G> List<G> emptyList() {
		return java.util.Collections.emptyList();

	}

	public static final <K, V> Map<K, V> emptyMap() {

		return java.util.Collections.emptyMap();
	}

	public static <G> Set<G> singleton(G o) {
		return java.util.Collections.singleton(o);

	}

	public static <G> List<G> singletonList(G o) {
		return java.util.Collections.singletonList(o);

	}

	public static <K, V> Map<K, V> singletonMap(K key, V value) {
		return java.util.Collections.singletonMap(key, value);

	}

	public static <G> List<G> nCopies(int n, G o) {
		return java.util.Collections.nCopies(n, o);

	}

	public static <G> Comparator<G> reverseOrder() {
		return java.util.Collections.reverseOrder();

	}

	public static <G> Comparator<G> reverseOrder(Comparator<G> cmp) {
		return java.util.Collections.reverseOrder(cmp);

	}

	public static <G> Enumeration<G> enumeration(final Collection<G> c) {
		return java.util.Collections.enumeration(c);

	}

	public static <G> ArrayList<G> list(Enumeration<G> e) {
		return java.util.Collections.list(e);

	}

	public static int frequency(Collection<?> c, Object o) {

		return java.util.Collections.frequency(c, o);
	}

	public static boolean disjoint(Collection<?> c1, Collection<?> c2) {
		return java.util.Collections.disjoint(c1, c2);

	}

	@SafeVarargs
	public static <G> boolean addAll(Collection<? super G> c, G... elements) {
		return java.util.Collections.addAll(c, elements);

	}

	public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
		return java.util.Collections.newSetFromMap(map);

	}

	public static <G> Queue<G> asLifoQueue(Deque<G> deque) {
		return java.util.Collections.asLifoQueue(deque);

	}
}
